package org.qdog.pk.pkscrape.controller;

import org.qdog.pk.pkscrape.dao.Dao;
import org.qdog.pk.pkscrape.entity.Entity;
import org.qdog.pk.pkscrape.entity.EntityType;
import org.qdog.pk.pkscrape.entity.PersistentObject;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

/**
 * @since 08/2011
 */
@Component
public class EntityMgr {

  private Dao dao;

  /**
   * Creates or loads an entity from the database.  The id is extracted from the entity parameter.  If the entity does
   * not exist in the database, the entity passed in is added to the persistence context and returned.  If the entity
   * does exist, the persistent version of the entity is returned.
   *
   * @param entity the entity to load or make persistent
   * @return the entity
   */
  public <T extends Entity> T createOrLoadEntity(T entity) {
    if (entity == null) {
      return null;
    }
    return (T) createOrLoadEntityById(entity.getId());
  }

  /**
   * Creates or loads an entity from the database.  If the entity does
   * not exist in the database, the entity is created and made persistent.  If it already exists,
   * the persistent version of the entity is returned.
   *
   * @param entityId identifies the entity to load or create
   * @return the entity
   */
  public Entity createOrLoadEntityById(final String entityId) {
    if (entityId == null) {
      return null;
    }
    Entity entity = dao.loadById(entityId);
    if (entity == null) {
      entity = dao.persist(EntityType.createEntity(entityId));

    }
    return entity;
  }

  /**
   * @see {@link #createOrLoadEntity(org.qdog.pk.pkscrape.entity.Entity)}
   */
  public Collection<Entity> createOrLoadEntities(Collection<Entity> entities) {
    // TODO this could perform faster by loading multiple entities from the database at once
    Collection<Entity> newEntities = new ArrayList<Entity>(entities.size());
    for (Entity entity : entities) {
      newEntities.add(createOrLoadEntity(entity));
    }
    return newEntities;
  }

  @Resource(name = "dao")
  public void setDao(Dao dao) {
    this.dao = dao;
  }

  @Transactional(readOnly = true)
  public Collection<Entity> loadNewEntities() {
    return dao.loadNewEntities();
  }

  @Transactional(readOnly = true)
  public Collection<Entity> loadNewEntities(EntityType type) {
    return dao.loadNewEntities(type);
  }

  @Transactional(readOnly = true)
  public Collection<Entity> loadStaleEntities(EntityType type, Date lastUpdate) {
    return dao.loadStaleEntities(type, lastUpdate);
  }

  public <T extends PersistentObject> T save(T object) {
    return dao.persist(object);
  }

}
